package com.xbongbong.paas.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.ExcelConstant;
import com.xbongbong.paas.constant.TimeConstant;
import com.xbongbong.paas.exception.ExcelAnalysisException;
import com.xbongbong.paas.exception.ExcelTitleCheckException;
import com.xbongbong.paas.help.ImportRedisHelper;
import com.xbongbong.paas.help.ImportSendHelper;
import com.xbongbong.paas.pojo.ErrorExcelDataPojo;
import com.xbongbong.paas.pojo.FieldAttrEntityForImport;
import com.xbongbong.paas.pojo.ImportStatusPojo;
import com.xbongbong.paas.pojo.ReadExcelDataReturnPojo;
import com.xbongbong.paas.pojo.UniqueIndexPojo;
import com.xbongbong.paas.pojo.dto.ImportFormDataDTO;
import com.xbongbong.paas.pojo.dto.ImportMessageFormDataDTO;
import com.xbongbong.paas.pojo.imports.CellTitlePojo;
import com.xbongbong.paas.pojo.imports.CellValuePojo;
import com.xbongbong.paas.pojo.imports.RowGroupPojo;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisConstant;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.service.HandleImportService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.ImportErrorCodeEnum;
import com.xbongbong.pro.pojo.vo.PaasConfigGetVO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ErrorMessageConstant;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.QuotationEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;

/**
 * 客户导入数据处理
 * @author 魏荣杰
 * @date 2019/11/18 2:15 下午
 * @since v4.6.0
 * @version v4.6.0
 */
public class ExcelImportReadDataDelegated implements ExcelReadDataDelegated {
    private static final Logger LOG = LoggerFactory.getLogger(ExcelImportReadDataDelegated.class);
    /**
     * 是否是第一行数据
     */
    private boolean isFirstDataRow = true;
    /**
     * 是否是一组数据的第一条数据
     */
    private boolean isFirstGroupData = true;
    /**
     * 表头
     */
    private List<CellTitlePojo> cellTitlePojoList = new ArrayList<>();
    /**
     * 处理数据总数
     */
    private int totalSum = 0;
    /**
     * 表头长度
     */
    private int titleLength = 0;
    /**
     * 实际的总分片数，计算得到的数，一旦处理数据了，肯定有一个分片
     */
    private int totalFragmentation = 1;

    private List<String> firstCellList = new ArrayList<>();

    private ImportSendHelper importSendHelper;

    private PaasRedisHelper paasRedisHelper;
    private ImportRedisHelper importRedisHelper;

    private HandleImportService handleImportService;

    private List<RowGroupPojo> rowGroupPojoList = new ArrayList<>();

    private List<List<CellValuePojo>> cellValuePojoList = new ArrayList<>();

    private Integer uniqueIdentityColumnIndex;
    /**
     * 报价单特殊逻辑使用
     */
    List<Integer> quotationIdentityColumnIndex;

    private String groupTagValue = null;

    private JSONArray fieldJsonArray;

    private ReadExcelDataReturnPojo readExcelDataReturnPojo = new ReadExcelDataReturnPojo();
    /**
     * 查重字段定位
     */
    private UniqueIndexPojo uniqueIndexPojo;
    /**
     * 查重redis key
     */
    private String checkRepeatKey;

    private PaasConfigGetVO paasConfig;


    public ExcelImportReadDataDelegated(ImportSendHelper importSendHelper, PaasRedisHelper paasRedisHelper, HandleImportService handleImportService, ImportRedisHelper importRedisHelper, PaasConfigGetVO paasConfig) {
        this.importSendHelper = importSendHelper;
        this.paasRedisHelper = paasRedisHelper;
        this.handleImportService = handleImportService;
        this.importRedisHelper = importRedisHelper;
        this.paasConfig = paasConfig;
    }


    @Override
    public void readExcelData(String sheetName, int sheetIndex, int totalRowCount, int curRow, List<String> cellList) {
        if (isFirstDataRow) {
            isFirstDataRow = false;
            // 读取到第一行数据的时候，表头已经加载完成，先对表头进行校验
        }
    }


    @Override
    public ReadExcelDataReturnPojo readExcelData(String sheetName, int sheetIndex, int totalRowCount, int curRow, List<String> cellList, List<List<String>> titleLists, List<FieldAttrEntityForImport> fieldAttrEntityForImportList, ImportFormDataDTO importFormDataDTO) throws ExcelTitleCheckException,ExcelAnalysisException {
        Integer businessType = importFormDataDTO.getBusinessType();
        if (isFirstDataRow) {
            isFirstDataRow = false;
            for (List<String> titles : titleLists) {
                if (titles.size() > titleLength) {
                    titleLength = titles.size();
                }
            }
            // 表头封装处理，以及表头校验
            cellTitlePojoList = ExcelReaderUtil.getCellTitlePojoList(titleLists, fieldAttrEntityForImportList, titleLength);
            fieldJsonArray = JSON.parseArray(JSON.toJSONString(fieldAttrEntityForImportList));
            readExcelDataReturnPojo.setCellTitlePojoList(cellTitlePojoList);
            readExcelDataReturnPojo.setFieldJsonArray(fieldJsonArray);

            XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
            String corpid = importFormDataDTO.getCorpid();
            String userId = importFormDataDTO.getUserId();
            // 用户缓存处理
            String hashKey = corpid + "_" + userId;
            // 导入假进度
            // 保存初始的粗略分片大小
            int falseTotalFragmentation = totalRowCount / ExcelConstant.PER_READ_INSERT_BATCH_COUNT + 1;
            ImportStatusPojo importStatusPojo = new ImportStatusPojo(totalRowCount, 0, 0, 0, 0, false, falseTotalFragmentation, importFormDataDTO.getAttrList());
            BeanUtil.copyProperties(importFormDataDTO, importStatusPojo);
            importRedisHelper.updateImportStatus(hashKey, importStatusPojo, 0);

            paasRedisHelper.setValue(RedisPrefixConstant.IMPORT_START_FLAG_KEY, hashKey, BasicConstant.ONE_STRING, TimeConstant.SECONDS_EIGHT_HOUR);

            long startTime = DateTimeUtil.getLong();
            LOG.warn("import_" + corpid + "_" + userId + "_" + xbbRefTypeEnum.getAlias() + "_start,time=" + DateTimeUtil.getString(startTime, new SimpleDateFormat("yyyy-MM-dd HH:mm")) + ",totalRowNum=" + totalRowCount);
            paasRedisHelper.setValue(RedisPrefixConstant.IMPORT_LOG_TIME, hashKey, 0, RedisConstant.LONG_DURATION);
            paasRedisHelper.setValue(RedisPrefixConstant.IMPORT_LOG_START_TIME, hashKey, startTime, RedisConstant.LONG_DURATION);
        }



        // 可能在末尾缺少单元格的情况，补空串
        int size = cellList.size();
        if (size < titleLength) {
            for (int j = titleLength - size ; j > 0 ; j--) {
                cellList.add("");
            }
        }

        if (isFirstGroupData) {
            // 存储第一组的首行数据，用于处理同组数据合并单元格导致数据解析为空的问题
            firstCellList = new ArrayList<>(cellList);
            // 获取用于区分一组数据的索引值
            if (Objects.equals(importFormDataDTO.getSaasMark(), SaasMarkEnum.SAAS.getCode())) {
                // saas
                if (Objects.equals(businessType, XbbRefTypeEnum.QUOTATION.getCode())) {
                    // 报价单特殊处理
                    quotationIdentityColumnIndex = handleImportService.getQuotationIdentityColumnIndex(fieldAttrEntityForImportList, cellTitlePojoList);
                    if (quotationIdentityColumnIndex != null) {
                        groupTagValue = firstCellList.get(quotationIdentityColumnIndex.get(0)) + firstCellList.get(quotationIdentityColumnIndex.get(1));
                    }

                    checkRepeatKey = importFormDataDTO.getCorpid() + "-" + importFormDataDTO.getFormId() + "-" + QuotationEnum.GROUP_NUMBER.getAttr();
                } else {
                    // 其他业务
                    uniqueIndexPojo = handleImportService.getUniqueIdentityColumnIndex(businessType, fieldAttrEntityForImportList, cellTitlePojoList);
                    uniqueIdentityColumnIndex = uniqueIndexPojo.getIndex();
                    if (uniqueIdentityColumnIndex != null) {
                        groupTagValue = firstCellList.get(uniqueIdentityColumnIndex);
                    }

                    // corpid + formid + attr
                    checkRepeatKey = importFormDataDTO.getCorpid() + "-" + importFormDataDTO.getFormId() + "-" + uniqueIndexPojo.getAttr();

                }
            } else {
                // paas
                uniqueIndexPojo = getPaasUniqueIdentityColumnIndex(fieldAttrEntityForImportList, cellTitlePojoList);
                uniqueIdentityColumnIndex = uniqueIndexPojo.getIndex();
                if (uniqueIdentityColumnIndex != null) {
                    groupTagValue = firstCellList.get(uniqueIdentityColumnIndex);
                }
            }
        }


        // 虑数据内有合并单元格的情况，需要拆分单元格并赋值
        String firstUniqueValue = null;
        String uniqueValue = null;
        if (Objects.equals(businessType, XbbRefTypeEnum.QUOTATION.getCode())) {
            // 报价单
            if (quotationIdentityColumnIndex != null) {
                Integer firstIndex = quotationIdentityColumnIndex.get(0);
                Integer secondIndex = quotationIdentityColumnIndex.get(1);
                firstUniqueValue = firstCellList.get(firstIndex) + firstCellList.get(secondIndex);
                uniqueValue = cellList.get(firstIndex) + cellList.get(secondIndex);
                if (StringUtil.isEmpty(cellList.get(firstIndex)) || StringUtil.isEmpty(cellList.get(secondIndex))) {
                    cellList.set(firstIndex, firstCellList.get(firstIndex));
                    cellList.set(secondIndex, firstCellList.get(secondIndex));
                    uniqueValue = firstUniqueValue;
                }
            }
        } else {
            // 其他
            if (uniqueIdentityColumnIndex != null) {
                firstUniqueValue = firstCellList.get(uniqueIdentityColumnIndex);
                uniqueValue = cellList.get(uniqueIdentityColumnIndex);

                if (StringUtil.isEmpty(uniqueValue)) {
                    // 如果为空，则获取一组的首行数据的关键值填充
                    cellList.set(uniqueIdentityColumnIndex, firstUniqueValue);
                    uniqueValue = firstUniqueValue;
                }
            }
        }

        // 封装一组数据
        List<CellValuePojo> cellValuePojos = new ArrayList<>();
        for (CellTitlePojo titlePojo : cellTitlePojoList) {
            String cellValue = cellList.get(titlePojo.getColumnIndex());
            CellValuePojo cellValuePojo = new CellValuePojo(cellValue, titlePojo.getTitle(), titlePojo.getParentTitle(), titlePojo.getSecondParentTitle(), titlePojo.getThirdParentTitle(), titlePojo.getColumnIndex());
            cellValuePojos.add(cellValuePojo);
        }

        // 当不是一组数据的第一行数据的时候处理合并单元格为空值的问题
        if (isFirstGroupData) {
            isFirstGroupData = false;
            RowGroupPojo rowGroupPojo = new RowGroupPojo(groupTagValue);
            cellValuePojoList.add(cellValuePojos);
            rowGroupPojo.setRowValueList(new ArrayList<>(cellValuePojoList));
            rowGroupPojoList.add(rowGroupPojo);
            cellValuePojoList.clear();
        } else {
            if (uniqueValue != null && firstUniqueValue != null) {
                if (Objects.equals(uniqueValue, firstUniqueValue)) {
                    RowGroupPojo rowGroupPojo = rowGroupPojoList.get(rowGroupPojoList.size() - 1);
                    // 产品限制600个规格，其他业务限制260条子表单数据
                    Integer maxRowNum = paasConfig.getSelectProductRowNum();
                    if (paasConfig.getSubFormRowNum() > paasConfig.getSelectProductRowNum()) {
                        maxRowNum = paasConfig.getSubFormRowNum();
                    }
                    if (Objects.equals(businessType, XbbRefTypeEnum.PRODUCT.getCode()) && rowGroupPojo.getRowValueList().size() > 600) {
                        throw new ExcelTitleCheckException(ImportErrorCodeEnum.API_ERROR_235040.getMsg());
                    } else if (!Objects.equals(businessType, XbbRefTypeEnum.PRODUCT.getCode()) && rowGroupPojo.getRowValueList().size() > maxRowNum) {
                        throw new ExcelTitleCheckException(String.format(ImportErrorCodeEnum.API_ERROR_235039.getMsg(), maxRowNum));
                    }
                    rowGroupPojo.getRowValueList().add(cellValuePojos);
                } else {
                    // 更新groupTagValue, 保存当前读到的行数据
                    groupTagValue = uniqueValue;
                    RowGroupPojo rowGroupPojo = new RowGroupPojo(groupTagValue);
                    cellValuePojoList.add(cellValuePojos);
                    rowGroupPojo.setRowValueList(new ArrayList<>(cellValuePojoList));
                    rowGroupPojoList.add(rowGroupPojo);

                    // 更新firstCellLis, cellValuePojoList
                    firstCellList = new ArrayList<>(cellList);
                    cellValuePojoList.clear();
                }
            } else {
                RowGroupPojo rowGroupPojo = new RowGroupPojo(groupTagValue);
                cellValuePojoList.add(cellValuePojos);
                rowGroupPojo.setRowValueList(new ArrayList<>(cellValuePojoList));
                rowGroupPojoList.add(rowGroupPojo);
                // 更新firstCellLis, cellValuePojoList
                firstCellList = new ArrayList<>(cellList);
                cellValuePojoList.clear();

            }
        }

        totalSum = rowGroupPojoList.size();


        // 导入数据前置查重 以及 其他用户同时导入查重
        // 100组数据到了，则发送到mq进行处理, 大于是为了防止最后一组数据有子表单
        if (totalSum > ExcelConstant.PER_READ_INSERT_BATCH_COUNT) {
            // 分片数加1
            totalFragmentation ++;
            // 临时存储第101组数据
            RowGroupPojo rowGroupPojo = rowGroupPojoList.get(rowGroupPojoList.size() - 1);
            // 移除第101组数据
            rowGroupPojoList.remove(rowGroupPojoList.size() - 1);

            if (Objects.equals(importFormDataDTO.getSaasMark(), SaasMarkEnum.SAAS.getCode())) {
                // saas
                if (Objects.equals(importFormDataDTO.getBusinessType(), XbbRefTypeEnum.QUOTATION.getCode()) || Objects.equals(importFormDataDTO.getBusinessType(), XbbRefTypeEnum.CONTRACT.getCode())) {
                    try {
                        rowGroupPojoList = handleImportService.handleDiscount(rowGroupPojoList, fieldAttrEntityForImportList);
                    } catch (XbbException e) {
                        throw new ExcelAnalysisException(e.getMessage());
                    }
                }
            }


//            if (Objects.equals(businessType, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode()) && ) {
//                // 客户有全局判重 走特殊逻辑
//                // 如果开启全局查重 走业务 其他走formId
//                checkRepeatKey = importFormDataDTO.getCorpid() + "_" + businessType + "_" + uniqueIndexPojo.getAttr();
//            } else {
//                if (Objects.equals(businessType, XbbRefTypeEnum.QUOTATION.getCode())) {
//                    // 报价单导入查重字段固定
//                    uniqueIndexPojo.setAttr(QuotationEnum.GROUP_NUMBER.getAttr());
//                }
//                // corpid + formid + attr
//                checkRepeatKey = importFormDataDTO.getCorpid() + "_" + importFormDataDTO.getFormId() + "_" + uniqueIndexPojo.getAttr();
//
//            }
            // TODO: 2021/1/29 优先处理客户的，其他模块后续做
            if (Objects.equals(businessType, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())) {
                String attr = uniqueIndexPojo.getAttr();
                if (Objects.nonNull(attr) && !Objects.equals(attr, "null")) {
                    List<ErrorExcelDataPojo> errorList = new ArrayList<>();
                    Iterator<RowGroupPojo> iterator = rowGroupPojoList.iterator();
                    while (iterator.hasNext()) {
                        RowGroupPojo next = iterator.next();
                        String groupTagValue = next.getGroupTagValue();
                        Boolean isRepeat = importRedisHelper.checkImportRepeat(checkRepeatKey, groupTagValue);
                        if (isRepeat) {
                            // 有重复数据 扔到错误队列
                            ErrorExcelDataPojo errorExcelDataPojo = new ErrorExcelDataPojo(I18nMessageUtil.getMessage(ErrorMessageConstant.EXCEL_DUPLICATE_OR_OTHER_IMPORT), next);
                            errorList.add(errorExcelDataPojo);
                            iterator.remove();
                        }
                    }
                    if (errorList.size() != 0) {
                        String hashKey = importFormDataDTO.getCorpid() + "_" + importFormDataDTO.getUserId();
                        String formHashKey = hashKey + "_" + importFormDataDTO.getFormId();
                        importRedisHelper.updateImportList(RedisPrefixConstant.IMPORT_ERROR_EXCEL_KEY, formHashKey, errorList, RedisConstant.LONG_DURATION);

                        ImportStatusPojo importStatusPojo = new ImportStatusPojo();
                        importStatusPojo.setSuccessNum(0);
                        importStatusPojo.setErrorNum(errorList.size());
                        importStatusPojo.setUpdateNum(0);
                        importStatusPojo.setNoSignNum(0);
                        importRedisHelper.updateImportStatus(hashKey, importStatusPojo, 0);
                        paasRedisHelper.setValue(RedisPrefixConstant.IMPORT_START_FLAG_KEY, hashKey, BasicConstant.ONE_STRING, TimeConstant.SECONDS_EIGHT_HOUR);
                    }
                }
            }



            // 发送到mq处理
            try {
                ImportMessageFormDataDTO message = new ImportMessageFormDataDTO();
                // 总行数
                message.setTotalSize(totalRowCount);
                List<ImportMessageFormDataDTO.RowGroupPojo> staticRowGoupPojoList = new ArrayList<>(rowGroupPojoList.size());
                BeanUtil.copyPropertiesList(rowGroupPojoList, staticRowGoupPojoList, ImportMessageFormDataDTO.RowGroupPojo.class);
                message.setRowGroupPojoList(staticRowGoupPojoList);

                int totalRowNum = 0;
                for (RowGroupPojo groupPojo : rowGroupPojoList) {
                    totalRowNum += groupPojo.getRowValueList().size();
                }
                message.setTotalRowNum(totalRowNum);
                message.setImportFormDataDTO(importFormDataDTO);
                List<ImportMessageFormDataDTO.CellTitlePojo> staticTitlePojoList = new ArrayList<>(cellTitlePojoList.size());
                BeanUtil.copyPropertiesList(cellTitlePojoList, staticTitlePojoList, ImportMessageFormDataDTO.CellTitlePojo.class);
                message.setTitlePojoLis(staticTitlePojoList);
                message.setJsonArray(fieldJsonArray);
                message.setCheckRepeatKey(checkRepeatKey);
                importSendHelper.sendMessage(message);
            } catch (Exception e) {
                // TODO: 2019/11/21
                LOG.error("com.xbongbong.paas.util.CustomerExcelReadDataDelegated.readExcelData() rabbitmq send message error", e);
            }

            totalSum = 0;
            // 清除rowGroupPojoList
            rowGroupPojoList.clear();
            // 保留最后一组数据，101组
            rowGroupPojoList.add(rowGroupPojo);

        }
        readExcelDataReturnPojo.setRowGroupPojoList(rowGroupPojoList);
        readExcelDataReturnPojo.setTotalFragmentation(totalFragmentation);
        readExcelDataReturnPojo.setCheckRepeatKey(checkRepeatKey);

//        LOG.info("sheet名称：" + sheetName + " sheet索引值：" + sheetIndex + " 总行数为：" + totalRowCount + " 行号为：" + curRow + " 数据：" + cellList);

        return readExcelDataReturnPojo;
    }


    /**
     * Description: 获取paas的分组表示index
     * @param fieldAttrEntityForImportList
     * @param cellTitlePojoList
     * @return java.lang.Integer
     * @author 魏荣杰
     * @date 2019/11/26 4:29 下午
     * @since v4.6.1
     */
    private UniqueIndexPojo getPaasUniqueIdentityColumnIndex(List<FieldAttrEntityForImport> fieldAttrEntityForImportList, List<CellTitlePojo> cellTitlePojoList) {
        UniqueIndexPojo uniqueIndexPojo = new UniqueIndexPojo();
        for (FieldAttrEntityForImport item : fieldAttrEntityForImportList) {
            if (Objects.equals(item.getNoRepeat(), 1)) {
                String attrName = item.getAttrName();
                for (CellTitlePojo titlePojo : cellTitlePojoList) {
                    if (Objects.equals(titlePojo.getTitle(), attrName)) {
                        uniqueIndexPojo.setIndex(titlePojo.getColumnIndex());
                        uniqueIndexPojo.setAttr(item.getAttr());
                        return uniqueIndexPojo;
                    }
                }
            }
        }
        return uniqueIndexPojo;
    }
}
